package com.zeta.demo.seata.controller;

import cn.hutool.core.thread.ThreadUtil;
import com.alibaba.ttl.threadpool.TtlExecutors;
import com.zeta.demo.seata.model.entity.DemoSeata;
import com.zeta.demo.seata.service.IDemoSeataService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.PreDestroy;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.zetaframework.annotation.log.SysLog;
import org.zetaframework.annotation.satoken.PreAuth;
import org.zetaframework.base.result.ApiResult;
import org.zetaframework.controller.SuperSimpleController;

import java.util.concurrent.ThreadPoolExecutor;

/**
 * Seata测试
 *
 * @author gcc
 */
@Slf4j
@PreAuth(enabled = false)
@Tag(name = "Seata测试", description = "Seata测试")
@RestController
@RequestMapping("/demo/seata")
@RequiredArgsConstructor
public class DemoSeataController extends SuperSimpleController<IDemoSeataService, DemoSeata>
{
    /** 创建线程池 */
    private static final ThreadPoolExecutor EXECUTOR = ThreadUtil.newExecutor(4, 10);
    /** 记得在适当时候关闭线程池 */
    @PreDestroy
    public void shutdown() {
        EXECUTOR.shutdown();
    }


    /**
     * 测试seata
     *
     * @return ApiResult<Boolean>
     */
    @SysLog
    @Operation(summary = "测试seata事务回滚")
    @PostMapping("/test")
    public ApiResult<Boolean> testSeata() {
        return success(service.testSeata());
    }


    /**
     * 测试多线程中打印TraceId
     *
     * 说明：
     * 参考：{@link org.zetaframework.core.utils.MdcContextUtil }
     *
     * @return ApiResult<Boolean>
     */
    @SysLog(value = "测试多线程中打印TraceId")  // <--- 测试OpenFeign请求有没有携带traceId
    @GetMapping("/test/traceId")
    public ApiResult<Boolean> testLog() {
        log.info("testLog start");

        // 说明：使用自定义线程池，需要用TtlExecutors包一下
        TtlExecutors.getTtlExecutor(EXECUTOR).execute(() -> {
            log.info("testLog threading: {} ", Thread.currentThread().getName());
        });

        service.testMdcLogAsync();

        log.info("testLog end");

        return success(true);
    }

}
